﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Text.RegularExpressions;
using System.Data.SqlClient;
using ICSharpCode.AvalonEdit;
using ICSharpCode.AvalonEdit.Highlighting;
using System.Xml;
using ICSharpCode.AvalonEdit.Document;
using System.Data.Common;
using System.Windows.Input;
using WeifenLuo.WinFormsUI.Docking;
using System.Windows.Controls;

namespace GameDBManager.Forms
{
	public partial class SqlEdit : Apq.Windows.Forms.DockDocForm, Apq.Editor.ITextEditor
	{
		public DBIs DBIs = new DBIs();
		public SqlOut SqlOut = new SqlOut();
		public Apq.Windows.Forms.DockForms.ErrList ErrList = new Apq.Windows.Forms.DockForms.ErrList();
		public Favorites Favorites = new Favorites();

		public Apq.DBC.XSD dsDBC
		{
			get { return _dsDBC; }
		}

		public SqlEdit()
		{
			InitializeComponent();

			#region 构建右键菜单
			System.Windows.Controls.MenuItem miCut = new System.Windows.Controls.MenuItem();
			miCut.Header = Apq.GlobalObject.UILang["剪切(_T)"];
			miCut.Click += new System.Windows.RoutedEventHandler(miCut_Click);
			cmsEditor.Items.Add(miCut);
			System.Windows.Controls.MenuItem miCopy = new System.Windows.Controls.MenuItem();
			miCopy.Header = Apq.GlobalObject.UILang["复制(_C)"];
			miCopy.Click += new System.Windows.RoutedEventHandler(miCopy_Click);
			cmsEditor.Items.Add(miCopy);
			System.Windows.Controls.MenuItem miPaste = new System.Windows.Controls.MenuItem();
			miPaste.Header = Apq.GlobalObject.UILang["粘贴(_P)"];
			miPaste.Click += new System.Windows.RoutedEventHandler(miPaste_Click);
			cmsEditor.Items.Add(miPaste);
			cmsEditor.Items.Add(new Separator());
			System.Windows.Controls.MenuItem miSelectAll = new System.Windows.Controls.MenuItem();
			miSelectAll.Header = Apq.GlobalObject.UILang["全选(_L)"];
			miSelectAll.Click += new System.Windows.RoutedEventHandler(miSelectAll_Click);
			cmsEditor.Items.Add(miSelectAll);
			#endregion

			DBIs.SqlEditDoc = this;
			SqlOut.SqlEdit = this;

			txtSql.Encoding = System.Text.Encoding.UTF8;

			txtSql.IsReadOnly = false;
			//txtSql.Options.ShowSpaces = true;
			//txtSql.Options.ShowTabs = true;
			txtSql.Options.EnableRectangularSelection = true;
			txtSql.Options.EnableTextDragDrop = true;
			txtSql.Options.ShowEndOfLine = false;
			txtSql.ShowLineNumbers = true;
			txtSql.WordWrap = false;
			txtSql.Options.AllowScrollBelowDocument = true;
			txtSql.ContextMenu = cmsEditor;
			txtSql.KeyUp += new System.Windows.Input.KeyEventHandler(txtSql_KeyUp);
			txtSql.KeyDown += new System.Windows.Input.KeyEventHandler(txtSql_KeyDown);

			elementHost1.Child = txtSql;
		}

		#region 右键菜单
		void miCut_Click(object sender, System.Windows.RoutedEventArgs e)
		{
			if (!string.IsNullOrEmpty(txtSql.SelectedText))
			{
				txtSql.Cut();
			}
		}

		void miCopy_Click(object sender, System.Windows.RoutedEventArgs e)
		{
			if (!string.IsNullOrEmpty(txtSql.SelectedText))
			{
				txtSql.Copy();
			}
		}

		void miPaste_Click(object sender, System.Windows.RoutedEventArgs e)
		{
			txtSql.Paste();
		}

		void miSelectAll_Click(object sender, System.Windows.RoutedEventArgs e)
		{
			txtSql.SelectAll();
		}
		#endregion

		private TextEditor txtSql = new TextEditor();
		private System.Windows.Controls.ContextMenu cmsEditor = new System.Windows.Controls.ContextMenu();

		private static string[] aryGo = { "\r\ngo\r\n", "\r\ngO\r\n", "\r\nGo\r\n", "\r\nGO\r\n" };

		private List<Thread> thds = new List<Thread>();

		public override void SetUILang(Apq.UILang.UILang UILang)
		{
			Text = UILang["Sql编辑"];

			#region 工具栏
			tsbOpen.Text = UILang["打开(&O)"];
			tsbSave.Text = UILang["保存(&S)"];
			tsbSaveAs.Text = UILang["另存为(&A)"];

			tsbExec.Text = UILang["执行(&X)"];
			tsbCancel.Text = UILang["取消(&C)"];
			tsbSingleThread.Text = UILang["单线程"];

			tssbResult.Text = UILang["结果显示方式"];
			tsmiResult0.Text = UILang["分列"];
			tsmiResult1.Text = UILang["合并"];

			tsddbView.Text = UILang["视图(&V)"];
			tsmiDBI.Text = UILang["数据库列表(&L)"];
			tsmiOut.Text = UILang["输出(&O)"];
			tsmiErrList.Text = UILang["错误列表(&E)"];

			tsbExport.Text = UILang["导出(&T)"];
			#endregion

			#region 对话框
			ofd.Filter = UILang["Sql文件(*.sql)|*.sql|所有文件(*.*)|*.*"];
			sfd.Filter = UILang["Sql文件(*.sql)|*.sql|所有文件(*.*)|*.*"];
			#endregion
		}

		private void SqlEdit_Load(object sender, EventArgs e)
		{
			#region 添加图标
			//Icon = new Icon(@"Res\ico\sign125.ico");

			this.tsmiUndo.Image = System.Drawing.Image.FromFile(Application.StartupPath + @"\Res\png\Editor\Undo.png");
			this.tsmiRedo.Image = System.Drawing.Image.FromFile(Application.StartupPath + @"\Res\png\Editor\Redo.png");
			this.tsmiCut.Image = System.Drawing.Image.FromFile(Application.StartupPath + @"\Res\png\Editor\Cut.png");
			this.tsmiCopy.Image = System.Drawing.Image.FromFile(Application.StartupPath + @"\Res\png\Editor\Copy.png");
			this.tsmiPaste.Image = System.Drawing.Image.FromFile(Application.StartupPath + @"\Res\png\Editor\Paste.png");
			this.tsbOpen.Image = System.Drawing.Image.FromFile(Application.StartupPath + @"\Res\png\File\Open.png");
			this.tsbSave.Image = System.Drawing.Image.FromFile(Application.StartupPath + @"\Res\png\File\Save.png");
			#endregion

			// Load our custom highlighting definition
			IHighlightingDefinition customHighlighting;
			using (XmlReader reader = new XmlTextReader(Application.StartupPath + @"\SQL2-Mode.xshd"))
			{
				customHighlighting = ICSharpCode.AvalonEdit.Highlighting.Xshd.
					HighlightingLoader.Load(reader, HighlightingManager.Instance);
			}
			// and register it in the HighlightingManager
			HighlightingManager.Instance.RegisterHighlighting("Custom Highlighting", new string[] { ".sql" }, customHighlighting);

			txtSql.SyntaxHighlighting = HighlightingManager.Instance.GetDefinitionByExtension(".sql");
			txtSql.Document.Changed += new EventHandler<DocumentChangeEventArgs>(txtSql_Changed);

			#region txtSql.Text
			string cfgtxtSql_Text = GlobalObject.XmlConfigChain[this.GetType(), "txtSql_Text"];
			if (cfgtxtSql_Text != null)
			{
				txtSql.Text = cfgtxtSql_Text;
			}
			/*
#if DEBUG
			if (string.IsNullOrEmpty(txtSql.Text))
			{
				txtSql.Text = @"
DECLARE @t table(ID int, ID1 int);
INSERT @t(ID, ID1)
SELECT 1,1
UNION ALL SELECT 2,2
UNION ALL SELECT 3,3
UNION ALL SELECT 4,4
UNION ALL SELECT 5,5
UNION ALL SELECT 6,6
UNION ALL SELECT 7,7
UNION ALL SELECT 8,8
UNION ALL SELECT 9,9
UNION ALL SELECT 10,10
UNION ALL SELECT 11,11
UNION ALL SELECT 12,12
UNION ALL SELECT 13,13
UNION ALL SELECT 14,14
UNION ALL SELECT 15,15
UNION ALL SELECT 16,16
UNION ALL SELECT 17,17
UNION ALL SELECT 18,18
UNION ALL SELECT 19,19
UNION ALL SELECT 20,20
UNION ALL SELECT 21,21;

SELECT t1.* FROM @t t1, @t t2;

SELECT 1,1
UNION ALL SELECT 2,2;";
			}
#endif
			 */
			#endregion

			DockFrame.tspbHelper.Completed += new Action<ToolStripProgressBar>(tspbHelper_Completed);
		}

		private void SqlEdit_Shown(object sender, EventArgs e)
		{
			tsmiErrList_CheckedChanged(sender, e);
			tsmiOut_CheckedChanged(sender, e);
			tsmiDBI_CheckedChanged(sender, e);
			tsmiFavorites_CheckedChanged(sender, e);
		}

		private void SqlEdit_FormClosing(object sender, FormClosingEventArgs e)
		{
		}

		#region IDataShow 成员
		/// <summary>
		/// 初始数据(如Lookup数据等)
		/// </summary>
		/// <param name="ds"></param>
		public override void InitData(DataSet ds)
		{
			#region 准备数据集结构
			dsDBC.DBI.Columns.Add("_Checked", typeof(bool));
			dsDBC.DBI.Columns.Add("_Expanded", typeof(bool));
			dsDBC.DBI.Columns.Add("_Selected", typeof(bool));
			dsDBC.DBI.Columns.Add("IsReadyToGo", typeof(bool));
			dsDBC.DBI.Columns.Add("Err", typeof(bool));
			#endregion

			#region 加载所有字典表
			#endregion
		}
		/// <summary>
		/// 加载数据
		/// </summary>
		/// <param name="ds"></param>
		public override void LoadData(DataSet ds)
		{
			dsDBC.Clear();
			dsDBC.DBI.Merge(GlobalObject.xsdDBC.DBI, false, MissingSchemaAction.Ignore);
		}
		#endregion

		private void txtSql_Changed(object sender, DocumentChangeEventArgs e)
		{
			GlobalObject.XmlConfigChain[this.GetType(), "txtSql_Text"] = txtSql.Text;
		}

		#region UI线程
		private void tssbResult_DropDownItemClicked(object sender, ToolStripItemClickedEventArgs e)
		{
			ToolStripMenuItem tsmi1 = e.ClickedItem as ToolStripMenuItem;
			if (tsmi1 != null)
			{
				tsmi1.Checked = true;
				ToolStripMenuItem tsmi2 = tssbResult.DropDownItems[System.Math.Abs(tssbResult.DropDownItems.IndexOf(tsmi1) - 1)] as ToolStripMenuItem;
				tsmi2.Checked = false;
			}
		}

		private void txtSql_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
		{
			if (e.Key == System.Windows.Input.Key.F5)
			{
				tsbExec_Click(sender, e);
			}
		}

		private void txtSql_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
		{
			if (ModifierKeys == Keys.Control && e.Key == Key.R)
			{
				DockFrame.DockDoc.Panes[1].DockState = (DockFrame.DockDoc.Panes[1].DockState == DockState.DockBottom) ?
					DockState.DockBottomAutoHide : DockState.DockBottom;
			}
		}

		private void tsbExec_Click(object sender, EventArgs e)
		{
			string strSql = txtSql.TextArea.Selection.GetText(txtSql.Document);
			if (string.IsNullOrEmpty(strSql))
			{
				strSql = txtSql.Text;
			}
			if (string.IsNullOrEmpty(strSql))
			{
				return;
			}

			#region 风险提示
			if (GlobalObject.XmlConfigChain["GameDBManager.Controls.MainOption.SqlEdit", "RiskHint"] == "1")
			{
				// 检测语句中是否含有风险语句并提示
				if (strSql.ToUpper().Contains("DELETE"))
				{
					if (MessageBox.Show(Apq.GlobalObject.UILang["检测到风险语句 DELETE,确定执行?"]
						, Apq.GlobalObject.UILang["风险提示"]
						, MessageBoxButtons.OKCancel, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2)
						!= DialogResult.OK)
					{
						return;
					}
				}
				Regex r = new Regex("((TRUNCATE|DROP)\\s+TABLE)\\s+[^@#]", RegexOptions.IgnoreCase);
				Match m = r.Match(strSql);
				if (m.Success)
				{
					string strSql_Risk = m.Groups[1].Value;
					if (MessageBox.Show(string.Format(Apq.GlobalObject.UILang["检测到风险语句 "] + "{0}" + Apq.GlobalObject.UILang[",确定执行?"], strSql_Risk), "风险提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2)
						!= DialogResult.OK)
					{
						return;
					}
				}
				r = new Regex("(UPDATE)\\s+[^@#]", RegexOptions.IgnoreCase);
				m = r.Match(strSql);
				if (m.Success)
				{
					string strSql_Risk = m.Groups[1].Value;
					if (MessageBox.Show(string.Format(Apq.GlobalObject.UILang["检测到风险语句 "] + "{0}" + Apq.GlobalObject.UILang[",确定执行?"], strSql_Risk), "风险提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2)
						!= DialogResult.OK)
					{
						return;
					}
				}
			}
			#endregion

			if (!string.IsNullOrEmpty(strSql))
			{
				#region 注册检测
#if !DEBUG
				DataView dv = new DataView(_dsDBC.DBI);
				dv.RowFilter = "_Checked = 1";
				if (dv.Count > 3 && !Apq.Reg.Client.Common.IsRegistration)
				{
					MessageBox.Show(Apq.GlobalObject.UILang["谢谢您支持共享软件!共享版最多支持同时勾选3个服务器。要获得更多的连接支持,请注册,谢谢使用！"],
						Apq.GlobalObject.UILang["注册提示"]);
					return;
				}
#endif
				#endregion

				tsbExec.Enabled = false;

				// 将线程中需要的控件值取到变量
				strSql += "\r\n";
				Apq.Windows.Controls.ControlExtension.SetControlValues(this, "arySql", strSql.Split(aryGo, StringSplitOptions.RemoveEmptyEntries));
				int nRIdx = tsmiResult1.Checked ? 1 : 0;
				Apq.Windows.Controls.ControlExtension.SetControlValues(this, "bliResult.ItemIndex", nRIdx);

				// 执行前保存配置文件
				GlobalObject.XmlConfigChain.Save();

				// 先终止上一次主后台线程
				Apq.Threading.Thread.Abort(MainBackThread);
				MainBackThread = Apq.Threading.Thread.StartNewThread(new ThreadStart(MainBackThread_Start));

				tsbCancel.Enabled = true;
			}
		}

		private void tsbCancel_Click(object sender, EventArgs e)
		{
			tsbCancel.Enabled = false;

			Apq.Threading.Thread.Abort(MainBackThread);
			foreach (Thread t in thds)
			{
				Apq.Threading.Thread.Abort(t);
				Application.DoEvents();
			}
			thds.Clear();
			DockFrame.tsslStatus.Text = Apq.GlobalObject.UILang["已取消"];
			DockFrame.tspb.Value = 0;

			tsbExec.Enabled = true;
		}

		private void tsbExport_Click(object sender, EventArgs e)
		{
			if (SqlOut.lstRts.Count > 0)
			{
				List<DataSet> lst = new List<DataSet>();
				foreach (DataSet ds in SqlOut.lstRts)
				{
					lst.Add(ds.Copy());
				}

				// 增加服务器列
				foreach (DataSet ds in lst)
				{
					foreach (DataTable dt in ds.Tables)
					{
						dt.Columns.Add("__DBIID", typeof(int));
						if (tsmiResult0.Checked)
						{//分列时多添加一列
							dt.Columns.Add("__DBIName");
						}

						// 设置第一个数据集的服务器名
						// 设置服务器名
						foreach (DataRow dr in dt.Rows)
						{
							dr["__DBIID"] = ds.ExtendedProperties["__DBIID"];
							dr["__DBIName"] = ds.DataSetName;
						}
					}
				}

				// 迭代合并表
				DataSet dsMerge = lst[0].Copy();
				for (int i = 1; i < lst.Count; i++)
				{
					dsMerge = Apq.Data.DataSetHelper.Merge(dsMerge, lst[i]);
				}

				Export FormE = new Export(dsMerge);
				FormE.ShowDialog(this);
			}
		}
		#endregion

		#region 后台线程
		/// <summary>
		/// 主后台线程入口,启动子线程/自己完成工作
		/// </summary>
		private void MainBackThread_Start()
		{
			// 取消选中的 空IP 行
			foreach (DataRow dr in _dsDBC.DBI)
			{
				string strIP = Apq.Convert.ChangeType<string>(dr["IP"]);
				if (string.IsNullOrWhiteSpace(strIP))
				{
					dr["_Checked"] = 0;
				}
			}

			DataView dv = new DataView(_dsDBC.DBI);
			dv.RowFilter = "_Checked = 1";
			if (dv.Count == 0)
			{
				Apq.Windows.Delegates.Action_UI<ToolStripButton>(this, tsbExec, delegate(ToolStripButton ctrl)
				{
					DockFrame.tsslStatus.Text = Apq.GlobalObject.UILang["未选择服务器"];
					tsbExec.Enabled = true;
				});
				return;
			}

			foreach (DataRow dr in _dsDBC.DBI.Rows)
			{
				dr["Err"] = false;
				dr["IsReadyToGo"] = false;
			}
			foreach (DataRowView drv in dv)
			{
				drv["IsReadyToGo"] = true;
			}

			if (tsbSingleThread.Checked)
			{
				Workers_Stop();

				foreach (DataRowView drv in dv)
				{
					Worker_Start(drv["DBIID"]);
				}
			}
			else
			{
				Workers_Stop();
				Workers_Start();
			}
		}

		/// <summary>
		/// 停止上次工作(主后台线程)
		/// </summary>
		private void Workers_Stop()
		{
			foreach (Thread t in thds)
			{
				Apq.Threading.Thread.Abort(t);
			}

			Apq.Windows.Delegates.Action_UI<ToolStripButton>(this, tsbExec, delegate(ToolStripButton ctrl)
			{
				DockFrame.tspb.Value = 0;
				DockFrame.tsslStatus.Text = Apq.GlobalObject.UILang["停止中..."];

				ErrList.ErrXSD.Clear();
				SqlOut.tc.TabPages.Clear();
			});
			foreach (DataSet item in SqlOut.lstRts)
			{
				item.Clear();			// 清空行
				item.Tables.Clear();	// 清空表
			}
			SqlOut.lstRts.Clear();//清空结果数据集列表
			thds.Clear();//清空子工作线程

			Apq.Windows.Delegates.Action_UI<ToolStripButton>(this, tsbExec, delegate(ToolStripButton ctrl)
			{
				DockFrame.tsslStatus.Text = Apq.GlobalObject.UILang["准备完成,开始处理..."];
			});
		}

		/// <summary>
		/// 开始一次工作(主后台线程)
		/// </summary>
		private void Workers_Start()
		{
			try
			{
				#region 获取服务器列表
				DataView dv = new DataView(_dsDBC.DBI);
				dv.RowFilter = "_Checked = 1";
				if (dv.Count == 0)
				{
					Apq.Windows.Delegates.Action_UI<ToolStripButton>(this, tsbExec, delegate(ToolStripButton ctrl)
					{
						DockFrame.tsslStatus.Text = Apq.GlobalObject.UILang["未选择服务器"];
						tsbExec.Enabled = true;
					});
					return;
				}
				#endregion

				#region 开始
				int nbliResult_ItemIndex = Apq.Convert.ChangeType<int>(Apq.Windows.Controls.ControlExtension.GetControlValues(this, "bliResult.ItemIndex"));
				Apq.Windows.Delegates.Action_UI<ToolStripButton>(this, tsbExec, delegate(ToolStripButton ctrl)
				{
					DockFrame.tsslStatus.Text = Apq.GlobalObject.UILang["启动中..."];
					DockFrame.tspb.Maximum = dv.Count;
				});

				foreach (DataRowView drv in dv)
				{
					ParameterizedThreadStart pts = new ParameterizedThreadStart(Worker_Start);
					try
					{
						Thread t = Apq.Threading.Thread.StartNewThread(pts, drv["DBIID"]);
						if (!Convert.IsDBNull(drv["DBIName"]))
						{
							t.Name = drv["DBIName"].ToString();
						}
						thds.Add(t);
					}
					catch (Exception ex)
					{
						Apq.GlobalObject.ApqLog.Warn("启动线程:", ex);
					}
				}
				#endregion
			}
			catch (ThreadAbortException)
			{
			}
			catch (Exception ex)
			{
				Apq.GlobalObject.ApqLog.Warn("执行中发生异常:", ex);
			}
		}

		/// <summary>
		/// 到一个服务器执行并显示结果[多线程入口]
		/// </summary>
		/// <param name="ServerID"></param>
		private void Worker_Start(object DBIID)
		{
			int nbliResult_ItemIndex = Apq.Convert.ChangeType<int>(Apq.Windows.Controls.ControlExtension.GetControlValues(this, "bliResult.ItemIndex"));
			string[] arySql = Apq.Windows.Controls.ControlExtension.GetControlValues(this, "arySql") as string[];

			DataView dvDBI = new DataView(_dsDBC.DBI);
			dvDBI.RowFilter = "DBIID = " + DBIID;

			DataRowView drv = dvDBI[0];
			int nDBIID = (int)DBIID;
			string DBIName = drv["DBIName"].ToString();

			DbConnection sc = null;
			try
			{
				sc = Apq.DBC.Common.CreateDBIConnection(DBIName, ref sc);
				Apq.Data.Common.DbConnectionHelper dch = new Apq.Data.Common.DbConnectionHelper(sc);

				DbDataAdapter sda = dch.CreateAdapter();

				sda.SelectCommand.CommandTimeout = 86400;//3600*24

				Apq.Data.Common.DbConnectionHelper.Open(sc);

				if (arySql != null)
				{
					TabPage tp = SqlOut.AddTabPage(nDBIID, DBIName);//显示当前服务器结果集

					int TableCount = 0;
					for (int i = 0; i < arySql.Length; i++)
					{
						DataSet ds1 = new DataSet();//先取到临时数据集
						sda.SelectCommand.CommandText = arySql[i];
						sda.Fill(ds1);

						//将取得的表加入到结果数据集
						foreach (DataTable ds1Table in ds1.Tables)
						{
							ds1Table.TableName = "Apq_Table" + TableCount++;

							if (nbliResult_ItemIndex == 1)
							{//合并显示时添加服务器列
								ds1Table.Columns.Add("__DBIName");

								foreach (DataRow dr1 in ds1Table.Rows)
								{
									dr1["__DBIName"] = DBIName;
								}
							}

							if (nbliResult_ItemIndex == 0)//分列显示
							{
								SqlOut.AddTable(tp, ds1Table.Copy());
							}
							else//合并显示
							{
								SqlOut.AddTable(SqlOut.tc.TabPages[0], ds1Table.Copy());
							}
						}
					}
				}
			}
			catch (ThreadAbortException)
			{
			}
			//catch (DbException ex)
			//{
			//}
			catch (Exception ex)
			{
				lock (LockUI)
				{
					// 标记本服执行出错
					drv["Err"] = true;

					Apq.Windows.Delegates.Action_UI<ToolStripButton>(this, tsbExec, delegate(ToolStripButton ctrl)
					{
						// 记录错误信息
						ErrList.AddRow(DateTime.Now, 4, 16, DBIName, ex.Message, Convert.ToInt32(DBIID));
					});
				}
				Apq.GlobalObject.ApqLog.Error(DBIName, ex);
			}
			finally
			{
				Apq.Data.Common.DbConnectionHelper.Close(sc);
				lock (LockUI)
				{
					Apq.Windows.Delegates.Action_UI<ToolStripButton>(this, tsbExec, delegate(ToolStripButton ctrl)
					{
						if (DockFrame.tspb.Value < DockFrame.tspb.Maximum)
						{
							DockFrame.tspbHelper.SetValue(DockFrame.tspb.Value + 1);
						}
					});
				}
			}
		}

		private void tspbHelper_Completed(ToolStripProgressBar obj)
		{
			Apq.Windows.Delegates.Action_UI<ToolStripButton>(this, tsbExec, delegate(ToolStripButton ctrl)
			{
				_dsDBC.DBI.AcceptChanges();
				DockFrame.tsslStatus.Text = Apq.GlobalObject.UILang["已全部完成"];
				tsbCancel.Enabled = false;
				tsbExec.Enabled = true;
				tsmiOut.Checked = true;

				// 显示错误
				if (_dsDBC.DBI.Select("Err = 1").Count() > 0)
				{
					DockFrame.tsslStatus.Text += Apq.GlobalObject.UILang[",但有错误发生,请查看"];
					tsmiErrList.Checked = true;
				}
			});
		}
		#endregion

		#region cms1
		private void tsmiUndo_Click(object sender, EventArgs e)
		{
			this.Undo();
		}

		private void tsmiRedo_Click(object sender, EventArgs e)
		{
			this.Redo();
		}

		private void tsmiCut_Click(object sender, EventArgs e)
		{
			this.Copy();
			this.Delete();
		}

		private void tsmiCopy_Click(object sender, EventArgs e)
		{
			this.Copy();
		}

		private void tsmiPaste_Click(object sender, EventArgs e)
		{
			this.Paste();
		}

		private void tsmiSelectAll_Click(object sender, EventArgs e)
		{
			this.SelectAll();
		}
		#endregion

		#region ITextEditor 成员

		protected string _FileName = string.Empty;
		public string FileName
		{
			get
			{
				return _FileName;
			}
			set
			{
				_FileName = value;
				Text = value;
				TabText = value;
			}
		}

		public void Save()
		{
			if (FileName.Length < 1)
			{
				SaveFileDialog saveFileDialog = new SaveFileDialog();
				saveFileDialog.RestoreDirectory = true;
				saveFileDialog.Filter = "文本文件(*.txt;*.sql)|*.txt;*.sql|所有文件(*.*)|*.*";
				if (saveFileDialog.ShowDialog(this) == DialogResult.OK)
				{
					FileName = saveFileDialog.FileName;
				}
				else
				{
					return;
				}
			}

			txtSql.Save(FileName);
		}

		public void SaveAs(string FileName)
		{
			this.FileName = FileName;
			Save();
		}

		public void Copy()
		{
			System.Windows.Forms.Clipboard.SetData(DataFormats.UnicodeText,
				txtSql.TextArea.Selection.IsEmpty ? txtSql.Text
				: txtSql.TextArea.Selection.GetText(txtSql.Document));
		}

		public void Delete()
		{
			for (int i = txtSql.TextArea.Selection.Segments.Count<ISegment>(); i >= 0; i--)
			{
				ISegment segment = txtSql.TextArea.Selection.Segments.ElementAt<ISegment>(i);
				txtSql.Document.Remove(segment);
			}
		}

		public void Open()
		{
			OpenFileDialog openFileDialog = new OpenFileDialog();
			openFileDialog.RestoreDirectory = true;
			openFileDialog.Filter = "文本文件(*.txt;*.sql)|*.txt;*.sql|所有文件(*.*)|*.*";
			if (openFileDialog.ShowDialog(this) == DialogResult.OK)
			{
				FileName = openFileDialog.FileName;
				txtSql.Load(FileName);
			}
		}

		public void Paste()
		{
			string str = System.Windows.Forms.Clipboard.GetData(DataFormats.UnicodeText) as string;
			//if (str != null) txtSql.Document.Insert(str);
		}

		public void Redo()
		{
			txtSql.Redo();
		}

		public void Reverse()
		{
		}

		public void SelectAll()
		{
		}

		public void Undo()
		{
			txtSql.Undo();
		}

		private void tsbOpen_Click(object sender, EventArgs e)
		{
			Open();
		}

		private void tsbSave_Click(object sender, EventArgs e)
		{
			Save();
		}

		private void tsbSaveAs_Click(object sender, EventArgs e)
		{
			SaveAs(FileName);
		}

		#endregion

		public void LoadFile(string FileName)
		{
			this.FileName = FileName;
			txtSql.Load(FileName);
		}

		#region 视图
		private void tsmiDBI_CheckedChanged(object sender, EventArgs e)
		{
			if (tsmiDBI.Checked)
			{
				DBIs.Show(DockFrame.DockDoc);
			}
			else
			{
				DBIs.Hide();
			}
		}

		private void tsmiOut_CheckedChanged(object sender, EventArgs e)
		{
			if (tsmiOut.Checked)
			{
				SqlOut.Show(DockFrame.DockDoc);
			}
			else
			{
				SqlOut.Hide();
			}
		}

		private void tsmiErrList_CheckedChanged(object sender, EventArgs e)
		{
			if (tsmiErrList.Checked)
			{
				ErrList.Show(DockFrame.DockDoc);
			}
			else
			{
				ErrList.Hide();
			}
		}

		private void tsmiFavorites_CheckedChanged(object sender, EventArgs e)
		{
			if (tsmiFavorites.Checked)
			{
				Favorites.Show(DockFrame.DockDoc);
			}
			else
			{
				Favorites.Hide();
			}
		}
		#endregion
	}
}
